import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:mockito/annotations.dart';
import 'package:flowplan_app/core/sync/offline_sync_service.dart';
import 'package:flowplan_app/core/offline/offline_data_manager.dart';
import 'package:flowplan_app/core/offline/offline_mode_manager.dart';
import 'package:flowplan_app/data/datasources/remote/note_api_service.dart';
import 'package:flowplan_app/data/datasources/remote/project_api_service.dart';
import 'package:flowplan_app/data/datasources/remote/todo_api_service.dart';
import 'package:flowplan_app/data/models/api_response.dart';
import 'package:flowplan_app/data/models/note_model.dart';
import 'package:flowplan_app/data/models/project_model.dart';
import 'package:flowplan_app/data/models/todo_model.dart';

// 生成Mock类
@GenerateMocks([
  NoteApiService,
  ProjectApiService,
  TodoApiService,
  OfflineDataManager,
  OfflineModeManager,
])
import 'offline_sync_service_test.mocks.dart';

void main() {
  group('离线同步服务测试', () {
    late MockNoteApiService mockNoteApiService;
    late MockProjectApiService mockProjectApiService;
    late MockTodoApiService mockTodoApiService;
    late MockOfflineDataManager mockOfflineDataManager;
    late MockOfflineModeManager mockOfflineModeManager;
    late OfflineSyncService offlineSyncService;

    setUp(() {
      mockNoteApiService = MockNoteApiService();
      mockProjectApiService = MockProjectApiService();
      mockTodoApiService = MockTodoApiService();
      mockOfflineDataManager = MockOfflineDataManager();
      mockOfflineModeManager = MockOfflineModeManager();
      
      offlineSyncService = OfflineSyncService();
    });

    group('初始化', () {
      test('成功初始化服务', () async {
        // 执行初始化
        await offlineSyncService.initialize(
          noteApiService: mockNoteApiService,
          projectApiService: mockProjectApiService,
          todoApiService: mockTodoApiService,
          offlineDataManager: mockOfflineDataManager,
          offlineModeManager: mockOfflineModeManager,
        );

        // 验证初始化成功（通过检查是否有错误抛出）
        expect(() => offlineSyncService.initialize(
          noteApiService: mockNoteApiService,
          projectApiService: mockProjectApiService,
          todoApiService: mockTodoApiService,
          offlineDataManager: mockOfflineDataManager,
          offlineModeManager: mockOfflineModeManager,
        ), returnsNormally);
      });
    });

    group('同步离线操作', () {
      test('同步创建笔记操作', () async {
        // 准备测试数据
        final operation = OfflineOperation(
          id: 'note_create_1',
          entityType: 'note',
          operationType: OfflineOperationType.create,
          data: {
            'title': '测试笔记',
            'content': '测试内容',
            'noteType': 'GENERAL',
            'tags': ['测试'],
            'authorId': 1,
            'isPublic': true,
          },
          timestamp: DateTime.now(),
        );

        final noteModel = NoteModel(
          id: 1,
          title: '测试笔记',
          content: '测试内容',
          noteType: NoteType.general,
          tags: ['测试'],
          authorId: 1,
          isPublic: true,
          createTime: DateTime.now(),
          updateTime: DateTime.now(),
        );

        final apiResponse = ApiResponse<NoteModel>(
          success: true,
          message: '成功',
          data: noteModel,
        );

        // 设置Mock行为
        when(mockOfflineDataManager.getOfflineOperations())
            .thenAnswer((_) async => [operation]);
        when(mockNoteApiService.createNote(any)).thenAnswer((_) async => apiResponse);
        when(mockOfflineDataManager.removeSyncedOperations(any))
            .thenAnswer((_) async {});

        // 执行同步
        await offlineSyncService.syncOfflineOperations();

        // 验证方法调用
        verify(mockNoteApiService.createNote(any)).called(1);
        verify(mockOfflineDataManager.removeSyncedOperations(['note_create_1'])).called(1);
      });

      test('同步更新笔记操作', () async {
        // 准备测试数据
        final operation = OfflineOperation(
          id: 'note_update_1',
          entityType: 'note',
          operationType: OfflineOperationType.update,
          data: {
            'id': 1,
            'title': '更新后的笔记',
            'content': '更新后的内容',
          },
          timestamp: DateTime.now(),
        );

        final noteModel = NoteModel(
          id: 1,
          title: '更新后的笔记',
          content: '更新后的内容',
          noteType: NoteType.general,
          tags: [],
          authorId: 1,
          isPublic: false,
          createTime: DateTime.now(),
          updateTime: DateTime.now(),
        );

        final apiResponse = ApiResponse<NoteModel>(
          success: true,
          message: '成功',
          data: noteModel,
        );

        // 设置Mock行为
        when(mockOfflineDataManager.getOfflineOperations())
            .thenAnswer((_) async => [operation]);
        when(mockNoteApiService.updateNote(any, any)).thenAnswer((_) async => apiResponse);
        when(mockOfflineDataManager.removeSyncedOperations(any))
            .thenAnswer((_) async {});

        // 执行同步
        await offlineSyncService.syncOfflineOperations();

        // 验证方法调用
        verify(mockNoteApiService.updateNote(1, any)).called(1);
        verify(mockOfflineDataManager.removeSyncedOperations(['note_update_1'])).called(1);
      });

      test('同步删除笔记操作', () async {
        // 准备测试数据
        final operation = OfflineOperation(
          id: 'note_delete_1',
          entityType: 'note',
          operationType: OfflineOperationType.delete,
          data: {
            'id': 1,
          },
          timestamp: DateTime.now(),
        );

        final apiResponse = ApiResponse<void>(
          success: true,
          message: '成功',
        );

        // 设置Mock行为
        when(mockOfflineDataManager.getOfflineOperations())
            .thenAnswer((_) async => [operation]);
        when(mockNoteApiService.deleteNote(any)).thenAnswer((_) async => apiResponse);
        when(mockOfflineDataManager.removeSyncedOperations(any))
            .thenAnswer((_) async {});

        // 执行同步
        await offlineSyncService.syncOfflineOperations();

        // 验证方法调用
        verify(mockNoteApiService.deleteNote(1)).called(1);
        verify(mockOfflineDataManager.removeSyncedOperations(['note_delete_1'])).called(1);
      });

      test('同步创建项目操作', () async {
        // 准备测试数据
        final operation = OfflineOperation(
          id: 'project_create_1',
          entityType: 'project',
          operationType: OfflineOperationType.create,
          data: {
            'projectName': '测试项目',
            'description': '测试项目描述',
            'priority': 'HIGH',
          },
          timestamp: DateTime.now(),
        );

        final projectModel = ProjectModel(
          id: 1,
          projectName: '测试项目',
          description: '测试项目描述',
          status: ProjectStatus.planning,
          priority: Priority.high,
          creatorId: 1,
          createTime: DateTime.now(),
          updateTime: DateTime.now(),
        );

        final apiResponse = ApiResponse<ProjectModel>(
          success: true,
          message: '成功',
          data: projectModel,
        );

        // 设置Mock行为
        when(mockOfflineDataManager.getOfflineOperations())
            .thenAnswer((_) async => [operation]);
        when(mockProjectApiService.createProject(any)).thenAnswer((_) async => apiResponse);
        when(mockOfflineDataManager.removeSyncedOperations(any))
            .thenAnswer((_) async {});

        // 执行同步
        await offlineSyncService.syncOfflineOperations();

        // 验证方法调用
        verify(mockProjectApiService.createProject(any)).called(1);
        verify(mockOfflineDataManager.removeSyncedOperations(['project_create_1'])).called(1);
      });

      test('同步更新项目操作', () async {
        // 准备测试数据
        final operation = OfflineOperation(
          id: 'project_update_1',
          entityType: 'project',
          operationType: OfflineOperationType.update,
          data: {
            'id': 1,
            'projectName': '更新后的项目',
            'status': 'IN_PROGRESS',
          },
          timestamp: DateTime.now(),
        );

        final projectModel = ProjectModel(
          id: 1,
          projectName: '更新后的项目',
          description: '测试项目描述',
          status: ProjectStatus.inProgress,
          priority: Priority.high,
          creatorId: 1,
          createTime: DateTime.now(),
          updateTime: DateTime.now(),
        );

        final apiResponse = ApiResponse<ProjectModel>(
          success: true,
          message: '成功',
          data: projectModel,
        );

        // 设置Mock行为
        when(mockOfflineDataManager.getOfflineOperations())
            .thenAnswer((_) async => [operation]);
        when(mockProjectApiService.updateProject(any, any)).thenAnswer((_) async => apiResponse);
        when(mockOfflineDataManager.removeSyncedOperations(any))
            .thenAnswer((_) async {});

        // 执行同步
        await offlineSyncService.syncOfflineOperations();

        // 验证方法调用
        verify(mockProjectApiService.updateProject(1, any)).called(1);
        verify(mockOfflineDataManager.removeSyncedOperations(['project_update_1'])).called(1);
      });

      test('同步删除项目操作', () async {
        // 准备测试数据
        final operation = OfflineOperation(
          id: 'project_delete_1',
          entityType: 'project',
          operationType: OfflineOperationType.delete,
          data: {
            'id': 1,
          },
          timestamp: DateTime.now(),
        );

        final apiResponse = ApiResponse<void>(
          success: true,
          message: '成功',
        );

        // 设置Mock行为
        when(mockOfflineDataManager.getOfflineOperations())
            .thenAnswer((_) async => [operation]);
        when(mockProjectApiService.deleteProject(any)).thenAnswer((_) async => apiResponse);
        when(mockOfflineDataManager.removeSyncedOperations(any))
            .thenAnswer((_) async {});

        // 执行同步
        await offlineSyncService.syncOfflineOperations();

        // 验证方法调用
        verify(mockProjectApiService.deleteProject(1)).called(1);
        verify(mockOfflineDataManager.removeSyncedOperations(['project_delete_1'])).called(1);
      });

      test('同步创建待办操作', () async {
        // 准备测试数据
        final operation = OfflineOperation(
          id: 'todo_create_1',
          entityType: 'todo',
          operationType: OfflineOperationType.create,
          data: {
            'projectId': 1,
            'title': '测试任务',
            'description': '测试任务描述',
            'priority': 'HIGH',
            'todoType': 'DEVELOP',
          },
          timestamp: DateTime.now(),
        );

        final todoModel = TodoModel(
          id: 1,
          projectId: 1,
          title: '测试任务',
          description: '测试任务描述',
          status: TodoStatus.todo,
          priority: Priority.high,
          todoType: TodoType.develop,
          reporterId: 1,
          createTime: DateTime.now(),
          updateTime: DateTime.now(),
        );

        final apiResponse = ApiResponse<TodoModel>(
          success: true,
          message: '成功',
          data: todoModel,
        );

        // 设置Mock行为
        when(mockOfflineDataManager.getOfflineOperations())
            .thenAnswer((_) async => [operation]);
        when(mockTodoApiService.createTodo(any)).thenAnswer((_) async => apiResponse);
        when(mockOfflineDataManager.removeSyncedOperations(any))
            .thenAnswer((_) async {});

        // 执行同步
        await offlineSyncService.syncOfflineOperations();

        // 验证方法调用
        verify(mockTodoApiService.createTodo(any)).called(1);
        verify(mockOfflineDataManager.removeSyncedOperations(['todo_create_1'])).called(1);
      });

      test('同步更新待办操作', () async {
        // 准备测试数据
        final operation = OfflineOperation(
          id: 'todo_update_1',
          entityType: 'todo',
          operationType: OfflineOperationType.update,
          data: {
            'id': 1,
            'title': '更新后的任务',
            'status': 'IN_PROGRESS',
          },
          timestamp: DateTime.now(),
        );

        final todoModel = TodoModel(
          id: 1,
          projectId: 1,
          title: '更新后的任务',
          description: '测试任务描述',
          status: TodoStatus.inProgress,
          priority: Priority.high,
          todoType: TodoType.develop,
          reporterId: 1,
          createTime: DateTime.now(),
          updateTime: DateTime.now(),
        );

        final apiResponse = ApiResponse<TodoModel>(
          success: true,
          message: '成功',
          data: todoModel,
        );

        // 设置Mock行为
        when(mockOfflineDataManager.getOfflineOperations())
            .thenAnswer((_) async => [operation]);
        when(mockTodoApiService.updateTodo(any, any)).thenAnswer((_) async => apiResponse);
        when(mockOfflineDataManager.removeSyncedOperations(any))
            .thenAnswer((_) async {});

        // 执行同步
        await offlineSyncService.syncOfflineOperations();

        // 验证方法调用
        verify(mockTodoApiService.updateTodo(1, any)).called(1);
        verify(mockOfflineDataManager.removeSyncedOperations(['todo_update_1'])).called(1);
      });

      test('同步删除待办操作', () async {
        // 准备测试数据
        final operation = OfflineOperation(
          id: 'todo_delete_1',
          entityType: 'todo',
          operationType: OfflineOperationType.delete,
          data: {
            'id': 1,
          },
          timestamp: DateTime.now(),
        );

        final apiResponse = ApiResponse<void>(
          success: true,
          message: '成功',
        );

        // 设置Mock行为
        when(mockOfflineDataManager.getOfflineOperations())
            .thenAnswer((_) async => [operation]);
        when(mockTodoApiService.deleteTodo(any)).thenAnswer((_) async => apiResponse);
        when(mockOfflineDataManager.removeSyncedOperations(any))
            .thenAnswer((_) async {});

        // 执行同步
        await offlineSyncService.syncOfflineOperations();

        // 验证方法调用
        verify(mockTodoApiService.deleteTodo(1)).called(1);
        verify(mockOfflineDataManager.removeSyncedOperations(['todo_delete_1'])).called(1);
      });
    });

    group('检查待同步操作', () {
      test('有待同步操作时返回true', () async {
        // 设置Mock行为
        when(mockOfflineDataManager.getOfflineOperations())
            .thenAnswer((_) async => [OfflineOperation(
              id: 'test_operation',
              entityType: 'note',
              operationType: OfflineOperationType.create,
              data: {'title': '测试'},
              timestamp: DateTime.now(),
            )]);

        // 执行检查
        final result = await offlineSyncService.hasPendingOperations();

        // 验证结果
        expect(result, isTrue);
      });

      test('没有待同步操作时返回false', () async {
        // 设置Mock行为
        when(mockOfflineDataManager.getOfflineOperations())
            .thenAnswer((_) async => []);

        // 执行检查
        final result = await offlineSyncService.hasPendingOperations();

        // 验证结果
        expect(result, isFalse);
      });
    });
  });
}